티스토리 뷰

새로운 프로젝트 시작하면서 새로운 언어와 프레임워크를 도입하게 되었다.
간단하게 Golang을 배우면서 Todo 앱을 만들어보기로 한다.

Golang ORM은 대부분 gorm을 많이 사용하나, 공식적으로 지원하는 DB가 적다. 최근까지 활발하게 업데이트도 되고 github 별점도 높으나
공식적으로 지원하는 DB가 한정적이라 일단 그다음으로 많은 xorm으로 적용해 보았다. 특별히 gorm과 많이 다르지 않아서 별 차이없는 없는 듯.
다만 22년 1월 현재기준. 20년 업데이트가 마지막이라 그 부분에서는 염려가 된다.

go get github.com/go-sql-driver/mysql
go get github.com/gin-gonic/gin
go get xorm.io/xorm

go-gin & xorm Todo

// main.go
package main

import (
   "fmt"
   _ "github.com/go-sql-driver/mysql"
   "todo/config"
   "todo/models"
   "todo/routes"
   "xorm.io/xorm"
)

var err error

func main() {
   dsn := config.DbURL(config.BuildDBConfig())
   config.DB, err = xorm.NewEngine("mysql", dsn)
   if err != nil {
      fmt.Println("status", err)
   }

   if err = config.DB.Sync2(new(models.Todo)); err != nil {
      fmt.Println("status", err)
   }

   r := routes.SetupRouter()

   r.Run()
}
//config
package config

import (
   "fmt"
   "xorm.io/xorm"
)

var DB *xorm.Engine

type DBConfig struct {
   Host     string
   Port     int
   User     string
   DBName   string
   Password string
}

func BuildDBConfig() *DBConfig {
   dbConfig := DBConfig{
      Host:     "",
      Port:     3306,
      User:     "",
      DBName:   "",
      Password: "",
   }
   return &dbConfig
}

func DbURL(dbConfig *DBConfig) string {
   return fmt.Sprintf(
      "%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
      dbConfig.User,
      dbConfig.Password,
      dbConfig.Host,
      dbConfig.Port,
      dbConfig.DBName,
   )
}
// controller/Togo.go
package controllers

import (
   "github.com/gin-gonic/gin"
   "net/http"
   "todo/models"
)

//GetList
func GetTodos(c *gin.Context) {
   var todo []models.Todo
   err := models.GetAllTodos(&todo)
   if err != nil {
      c.AbortWithStatus(http.StatusNotFound)
   } else {
      c.JSON(http.StatusOK, todo)
   }
}

//GetOne
func GetTodo(c *gin.Context) {
   id := c.Params.ByName("id")
   var todo models.Todo
   err := models.GetTodo(&todo, id)
   if err != nil {
      c.AbortWithStatus(http.StatusNotFound)
   } else {
      c.JSON(http.StatusOK, todo)
   }
}

//Create
func CreateTodo(c *gin.Context) {
   var todo models.Todo
   c.BindJSON(&todo)
   err := models.CreateTodo(&todo)
   if err != nil {
      c.AbortWithStatus(http.StatusNotFound)
   } else {
      c.JSON(http.StatusOK, todo)
   }
}

func UpdateTodo(c *gin.Context) {
   var todo models.Todo
   id := c.Params.ByName("id")

   models.GetTodo(&todo, id)

   todo.Title = c.PostForm("title")
   todo.Description = c.PostForm("description")

   err := models.UpdateTodo(&todo, id)
   if err != nil {
      c.AbortWithStatus(http.StatusNotFound)
   } else {
      c.JSON(http.StatusOK, todo)
   }
}

func DeleteTodo(c *gin.Context) {
   var todo models.Todo
   id := c.Params.ByName("id")
   err := models.DeleteTodo(&todo, id)
   if err != nil {
      c.AbortWithStatus(http.StatusNotFound)
   } else {
      c.JSON(http.StatusOK, gin.H{
         "id:" + id: "deleted",
      })
   }
}
//models/Togo.go
package models

import (
   "todo/config"
)

type Todo struct {
   Id          int64  `json:"id"`
   Title       string `json:"title"`
   Description string `json:"description"`
}

func (b *Todo) TableName() string {
   return "todo"
}

func GetAllTodos(todo *[]Todo) (err error) {
   if err = config.DB.Find(todo); err != nil {
      return err
   }
   return nil
}

func CreateTodo(todo *Todo) (err error) {
   _, err = config.DB.Insert(todo)
   if err != nil {
      return err
   }
   return nil
}

func GetTodo(todo *Todo, id string) (err error) {
   _, err = config.DB.ID(id).Get(todo)
   if err != nil {
      return err
   }
   return nil
}

func UpdateTodo(todo *Todo, id string) (err error) {
   _, err = config.DB.ID(id).Update(todo)
   if err != nil {
      return err
   }

   return nil
}

func DeleteTodo(todo *Todo, id string) (err error) {
   _, err = config.DB.ID(id).Delete(todo)
   if err != nil {
      return err
   }
   return nil
}
//rountes/Router.go
package routes

import (
   "github.com/gin-gonic/gin"
   "todo/controllers"
)

func SetupRouter() *gin.Engine {
   r := gin.Default()

   r.GET("/", func(c *gin.Context) {
      c.JSON(200, gin.H{
         "message": "hello world",
      })
   })

   todo := r.Group("/todo")
   {
      todo.GET("", controllers.GetTodos)
      todo.POST("", controllers.CreateTodo)

      todo.GET("/:id", controllers.GetTodo)
      todo.PUT("/:id", controllers.UpdateTodo)
      todo.DELETE("/:id", controllers.DeleteTodo)
   }
   return r
}
$ http localhost:8080/todo  
HTTP/1.1 200 OK
Content-Length: 289
Content-Type: application/json; charset=utf-8
Date: Fri, 21 Jan 2022 05:52:39 GMT

[
    {
        "description": "",
        "id": 1,
        "title": "aaa"
    },
    {
        "description": "test",
        "id": 2,
        "title": "aaa"
    },
]
$ http --form PUT localhost:8080/todo/2 "title=aaa" "description=test"
HTTP/1.1 200 OK
Content-Length: 45
Content-Type: application/json; charset=utf-8
Date: Fri, 21 Jan 2022 01:34:51 GMT

{
    "Id": "2",
    "description": "test",
    "title": "aaa"
}

'공부합시다 > Golang' 카테고리의 다른 글

Redis pub/sub in golang  (0) 2023.05.04
GVM으로 go설치하기  (0) 2023.03.30
golang 웹크롤링 예제  (0) 2023.03.15
댓글